#ifndef __diffmmmConfiguration_H__
#define __diffmmmConfiguration_H__

#include <MMM/Motion/Legacy/Converter/ConverterFactory.h>

#include <boost/extension/shared_library.hpp>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <filesystem>
#include <boost/foreach.hpp>
//#include <boost/algorithm/string/split.hpp>
//#include <boost/algorithm/string.hpp>

#include <string>
#include <iostream>
#include <VirtualRobot/RuntimeEnvironment.h>

// setup for converter plugin search, other search paths can be added with the command line parameter "libPath"
#ifdef WIN32
#define MMMConverter_LIB_EXTENSION ".dll"
#ifdef _DEBUG
#define MMMConverter_STANDARD_LIB_SEARCH_PATH MMMConverter_BASE_DIR "/../build/bin/Debug"
#else
#define MMMConverter_STANDARD_LIB_SEARCH_PATH MMMConverter_BASE_DIR "/../build/bin/Release"
#endif
#else
#define MMMConverter_LIB_EXTENSION ".so"
#define MMMConverter_STANDARD_LIB_SEARCH_PATH MMMConverter_BASE_DIR "/../build/lib/"
#endif

/*!
    Configuration of command line converter.
    By default some standard parameters are set.
*/
struct DiffmmmConfiguration
{
    //! Initialize with standard parameter set
    DiffmmmConfiguration() : diffMode(eOutputDetailed), motion1specified (false), motion2specified (false), outputFileSpecified(false)
    {
        mmmModelFile = std::string(diffmmm_BASE_DIR)+std::string("/../data/Model/Winter/mmm.xml");
    }

    //! checks for command line parameters and updates configuration accordingly.
    bool processCommandLine(int argc, char *argv[])
    {
        bool error = false;
        VirtualRobot::RuntimeEnvironment::considerKey("diffmode");
        VirtualRobot::RuntimeEnvironment::considerKey("modelfile");
        VirtualRobot::RuntimeEnvironment::considerKey("motionname1");
        VirtualRobot::RuntimeEnvironment::considerKey("motionname2");
        VirtualRobot::RuntimeEnvironment::considerKey("outputfile");
        VirtualRobot::RuntimeEnvironment::processCommandLine(argc,argv);
        std::vector<std::string> params = VirtualRobot::RuntimeEnvironment::getUnrecognizedOptions();
        if (params.size()!=2)
        {
            MMM_ERROR << "Need 2 Files!" << std::endl;
            error = true;
        }
        file1 = params[0];
        file2 = params[1];
        VirtualRobot::RuntimeEnvironment::addDataPath(diffmmm_BASE_DIR);

        VirtualRobot::RuntimeEnvironment::addDataPath(std::string(diffmmm_BASE_DIR)+"/..");
        VirtualRobot::RuntimeEnvironment::addDataPath(std::string(diffmmm_BASE_DIR)+"/../data/Model/Winter");


        if (VirtualRobot::RuntimeEnvironment::hasValue("diffmode"))
        {
            std::string diffmode = VirtualRobot::RuntimeEnvironment::getValue("diffmode");
            if (diffmode=="complete")
                this->diffMode = this->eOutputDetailed;
            else if (diffmode=="average")
                this->diffMode = this->eOutputAvgOnly;
            else if (diffmode=="overview")
                this->diffMode = this->eOutputOverviewOnly;
        }

        if (VirtualRobot::RuntimeEnvironment::hasValue("modelfile"))
        {
            mmmModelFile = VirtualRobot::RuntimeEnvironment::getValue("modelfile");
        }

        if (VirtualRobot::RuntimeEnvironment::hasValue("motionname1"))
        {
            motionName1 = VirtualRobot::RuntimeEnvironment::getValue("motionname1");
            motion1specified = true;
        }

        if (VirtualRobot::RuntimeEnvironment::hasValue("motionname2"))
        {
            motionName2 = VirtualRobot::RuntimeEnvironment::getValue("motionname2");
            motion2specified = true;
        }

        if (VirtualRobot::RuntimeEnvironment::hasValue("outputfile"))
        {
            outputFile = VirtualRobot::RuntimeEnvironment::getValue("outputfile");
            outputFileSpecified = true;
        }

        //GET ABSOLUTE PATHS
        if (!VirtualRobot::RuntimeEnvironment::getDataFileAbsolute(file1))
        {
            std::cout << "Could not find input file1: [" << file1 << "]!" << std::endl;
            error = true;
        }
        if (!VirtualRobot::RuntimeEnvironment::getDataFileAbsolute(file2))
        {
            std::cout << "Could not find input file2: [" << file2 << "]!" << std::endl;
            error = true;
        }

        if (error)
        {
            VirtualRobot::RuntimeEnvironment::print();
            return false;
        } else
            return true;
    }


    void print()
    {
        std::cout << "*** diffmmm configuration ***" << std::endl;
        //MMM_INFO << VirtualRobot::RuntimeEnvironment::
        std::cout << "File 1: [" << file1 << "], File 2: [" << file2 << "]" << std::endl;
        std::cout << "MMM Model File is [" << mmmModelFile << "]" << std::endl;
        std::cout << "*****************************" << std::endl;
    }

    void printSyntax()
    {
        std::cout << std::endl << "Syntax: diffmmm %motionfile1 %motionfile2 [--optionKey value]..." << std::endl << std::endl;
        std::cout << "OPTION\t\tVALUE\t\tDESCRIPTION" << std::endl;
        std::cout << "diffmode\t" << "complete\t" << "Do a complete analysis" << std::endl;
        std::cout << "\t\t" << "average\t\t" << "Only show average marker differences" << std::endl;
        std::cout << "\t\t" << "overview\t" << "Only show an overview of the analysis" << std::endl;
        std::cout << "motionname1\t" << "<name>\t\t" << "Specify the name of the motion, contained in the first motion file" << std::endl;
        std::cout << "motionname2\t" << "<name>\t\t" << "Specify the name of the motion, contained in the second motion file" << std::endl;
        std::cout << "outputfile\t" << "<filename>\t" << "Specify a file to redirect results to." << std::endl;
        std::cout << "modelfile\t" << "<filename>\t" << "Force a specific modelfile for the motion [NYI]" << std::endl;
        std::cout << std::endl;
    }

    enum DiffMode
    {
        eOutputDetailed,
        eOutputOverviewOnly,
        eOutputAvgOnly
    };

    std::string file1;
    std::string file2;
    std::string motionName1;
    std::string motionName2;
    std::string mmmModelFile;
    std::string outputFile;
    DiffMode diffMode;
    bool motion1specified;
    bool motion2specified;
    bool outputFileSpecified;
};

#endif //__diffmmmConfiguration_H__


